using UnityEngine;
using System.Collections;

[RequireComponent(typeof(PlayerPhys))]
public class PlayerControl : MonoBehaviour {
	
	// Player Handling
	public float gravity = 20;
	public float walkSpeed = 8;
	public float runSpeed = 12;
	public float acceleration = 30;
	public float jumpHeight = 12;

	//System
	private float animationSpeed;
	private float currentSpeed;
	private float targetSpeed;
	private Vector2 amountToMove;

	//States
	private bool jumping;

	//Components
	private PlayerPhys playerPhys;
	private Animator animator;

	void Start () {
		playerPhys = GetComponent<PlayerPhys>();
		animator = GetComponent<Animator>();

		animator.SetLayerWeight(1, 1);
	}
	
	void Update () {

		//reset acceleration upon collision
		if(playerPhys.movementStopped)
		{
			targetSpeed = 0;
			currentSpeed = 0;
		}

		//if player is touching the ground
		if(playerPhys.grounded)
		{
			amountToMove.y = 0;

			if(jumping)
			{
				jumping = false;
				animator.SetBool("Jumping", false);
			}

			//Jump
			if(Input.GetButtonDown("Jump"))
			{
				amountToMove.y = jumpHeight;
				jumping = true;
				animator.SetBool("Jumping", true);
			}
		}

		animationSpeed = IncrementTowards(animationSpeed, Mathf.Abs(targetSpeed), acceleration);
		animator.SetFloat("Speed", animationSpeed);

		//Input
		float speed = (Input.GetButton("Run"))?runSpeed:walkSpeed;
		targetSpeed = Input.GetAxisRaw("Horizontal") * speed;
		currentSpeed = IncrementTowards(currentSpeed, targetSpeed, acceleration);
	
		//Set amount to move
		amountToMove.x = currentSpeed;
		amountToMove.y -= gravity * Time.deltaTime;
		playerPhys.Move(amountToMove * Time.deltaTime);

		//Face direction
		float moveDir = Input.GetAxisRaw("Horizontal");
		if(moveDir != 0)
		{
			transform.eulerAngles = (moveDir>0)?Vector3.up * 180:Vector3.zero;
		}
	}	                       

	// Increase n towards target by speed
	private float IncrementTowards(float n, float target, float a) {
		if (n == target) {
			return n;	
		}
		else {
			float dir = Mathf.Sign(target - n); // must n be increased or decreased to get closer to target
			n += a * Time.deltaTime * dir;
			return (dir == Mathf.Sign(target-n))? n: target; // if n has now passed target then return target, otherwise return n
		}
	}

	

}
